package com.nxj.factory;

import com.nxj.annotations.MyAutowired;
import com.nxj.annotations.MyController;
import com.nxj.annotations.MySecurity;
import com.nxj.annotations.MyService;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.function.BiConsumer;

public class IOCFactory {

    static Map<String, Object> objects = new HashMap<>();
    static List<Class> classes = new ArrayList<>();

    static Properties properties = new Properties();

    public static void doAnnotation() throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException {
        System.out.println("开始初始化 IOC 容器...");
        // 1. 扫描全局类
        properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("springmvc.properties"));
        doScan(properties.getProperty("basePackages"));
        // 2. 加载所有的bean
        for (Class aClass : classes) {
            if (aClass.isAnnotationPresent(MyController.class)) {
                objects.put(toLowerFirst(aClass.getSimpleName()), aClass.newInstance());
            } else if (aClass.isAnnotationPresent(MyService.class)) {
                String beanId = toLowerFirst(aClass.getSimpleName());
                if (((MyService) aClass.getAnnotation(MyService.class)).value() != "")
                    beanId = ((MyService) aClass.getAnnotation(MyService.class)).value();
                objects.put(beanId, aClass.newInstance());
            }
        }
        // 3. 开始迭代注入
        objects.forEach((s, o) -> {
            for (Field declaredField : o.getClass().getDeclaredFields()) {
                if (!declaredField.isAnnotationPresent(MyAutowired.class)) continue;

                String beanId = declaredField.getName();
                if ((declaredField.getAnnotation(MyAutowired.class)).value() != "") {
                    beanId = declaredField.getAnnotation(MyAutowired.class).value();
                }
                declaredField.setAccessible(true);
                try {
                    declaredField.set(o, objects.get(beanId));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        });
        // 4. 初始化 mvc handleMapping
        HandlerMappingGenerator.doMappring();
    }

    public static void doScan(String basePackage) throws ClassNotFoundException {
        String basePath = (Thread.currentThread().getContextClassLoader().getResource("").getPath() + basePackage.replaceAll("\\.", "/")).replace("%20", " ");
        File file = new File(basePath);
        for (File oneFile : file.listFiles()) {
            if (oneFile.isDirectory()) {
                doScan(basePackage + "." + oneFile.getName());
            } else if (oneFile.getName().endsWith(".class")) {
                classes.add(Class.forName(basePackage + "." + oneFile.getName().replaceAll(".class", "")));
            }
        }
    }

    public static String toLowerFirst(String name) {
        char[] chars = name.toCharArray();
        if (chars[0] >= 'A' && chars[0] <= 'Z') chars[0] += 32;
        return String.valueOf(chars);
    }

    public Object getBean(String beanId) {
        return objects.get(beanId);
    }

    public Map<String, Object> beans() {
        return objects;
    }
}
